﻿
using System;
using System.Collections;
using System.Reflection;
using UnityEngine;

//存储
//PlayerPrefsDataMgr.Instance.Save(role, role.id.ToString());
//读取
//Role role2 = PlayerPrefsDataMgr.Instance.Load(typeof(Role), "100") as Role;

public class PlayerPrefsDataMgr
{
    private static PlayerPrefsDataMgr instance = new PlayerPrefsDataMgr();
    public static PlayerPrefsDataMgr Instance
    {
        get
        {
            return instance;
        }
    }

    private PlayerPrefsDataMgr(){}

    private string GetKey(string key, Type type, FieldInfo field)
    {
        return String.Format("{0}_{1}_{2}_{3}", key, type.Name, field.FieldType.Name, field.Name);
    }

    private void SaveValue(string keyName, object value)
    {
        Type fieldType = value.GetType();
        if (fieldType == typeof(int))
        {
            //数据加密
            int enValue = (int)value + 10;
            PlayerPrefs.SetInt(keyName, enValue);
        }
        else if (fieldType == typeof(float))
        {
            PlayerPrefs.SetFloat(keyName, (float)value);
        }
        else if (fieldType == typeof(string))
        {
            PlayerPrefs.SetString(keyName, value.ToString());
        }
        else if (fieldType == typeof(bool))
        {
            PlayerPrefs.SetInt(keyName, (bool)value?1:0);
        }
        //如何判断泛型类型的类型呢?
        //通过反射判断 父子关系
        //这里相当于是判断 字段是不是IList的子类
        else if (typeof(IList).IsAssignableFrom(fieldType))
        {
            //父类装子类
            IList list = value as IList;
            //存储长度
            PlayerPrefs.SetInt(keyName, list.Count);
            //存储列表
            int index = 0;
            foreach (object obj in list)
            {
                SaveValue(keyName + index, obj);
                ++index;
            }
        }
        //判断是不是Dictionary类型 通过Dictionary的父类来判断
        else if (typeof(IDictionary).IsAssignableFrom(fieldType))
        {
            //父类装子类
            IDictionary dic = value as IDictionary;
            //存储字典长度
            PlayerPrefs.SetInt(keyName, dic.Count);
            //遍历存储Dic里面的具体值
            int index = 0;
            foreach (object key in dic.Keys)
            {
                SaveValue(keyName + "_key_" + index, key);
                SaveValue(keyName + "_value_" + index, dic[key]);
                ++index;
            }
        }
        //基础数据类型都不是 那么可能是自定义类
        else
        {
            Save(value, keyName);
        }
    }

    /// <summary>
    /// 存储数据
    /// </summary>
    /// <param name="data"></param>  数据对象
    /// <param name="keyName"></param> 数据对象的唯一key
    public void Save(object data, string key)
    {
        //通过TYpe得到传入数据对象的所有字段
        //然后结合PlayerPrefs来进行存储
        Type dataType = data.GetType();
        #region 第一步：得到所有字段
        FieldInfo[] fields = dataType.GetFields();
        #endregion
        #region 第二步：定义key的规则 进行数据存储
        //key_数据类型_字段类型_字段名
        #endregion
        #region 第三步：遍历这些字段 进行数据存储
        for (int i = 0; i < fields.Length; i++)
        {
            SaveValue(GetKey(key, dataType, fields[i]), fields[i].GetValue(data));
        }
        PlayerPrefs.Save();
        #endregion
    }

    public object LoadValue(string key, Type fieldType)
    {
        if (fieldType == typeof(int))
        {
            //数据解密
            int deValue = PlayerPrefs.GetInt(key) - 10;
            return deValue;
        }
        else if (fieldType == typeof(float))
        {
            return PlayerPrefs.GetFloat(key);
        }
        else if (fieldType == typeof(string))
        {
            return PlayerPrefs.GetString(key);
        }
        else if (fieldType == typeof(bool))
        {
            return PlayerPrefs.GetInt(key) == 1 ? true : false;
        }
        else if (typeof(IList).IsAssignableFrom(fieldType))
        {
            //读取长度
            int count = PlayerPrefs.GetInt(key, 0);
            //父类装子类
            IList list = Activator.CreateInstance(fieldType) as IList;
            for (int i=0; i<count; i++)
            {
                //目的是要得到List中泛型的类型
                list.Add(LoadValue(key + i, fieldType.GetGenericArguments()[0]));
            }
            return list;
        }
        else if (typeof(IDictionary).IsAssignableFrom(fieldType))
        {
            //读取长度
            int count = PlayerPrefs.GetInt(key, 0);
            //父类装子类
            IDictionary dic = Activator.CreateInstance(fieldType) as IDictionary;
            Type[] kvType = fieldType.GetGenericArguments();
            //遍历
            for (int i=0; i<count; i++)
            {
                dic.Add(LoadValue(key + "_key_" + i, kvType[0]),
                        LoadValue(key + "_value_" + i, kvType[1]));
            }
            return dic;
        }
        return Load(fieldType, key);
    }

    /// <summary>
    /// 读取数据
    /// </summary>
    /// <param name="type"></param> 想要读取数据的 数据类型
    /// <param name="key"></param> 数据对象的唯一key
    /// <returns></returns>
    public object Load(Type type, string key)
    {
        //CreateInstance 必须要确保Class中有无参构造
        object data = Activator.CreateInstance(type);
        #region 第一步：得到所有字段
        FieldInfo[] fields = type.GetFields();
        #endregion
        #region 第二步：遍历这些字段 进行数据读取
        FieldInfo field;
        for (int i = 0; i < fields.Length; i++)
        {
            field = fields[i];
            field.SetValue(data, LoadValue(GetKey(key, type, field), field.FieldType));
        }
        #endregion
        //根据传入的类型和key
        //根据存储的数据和key拼接读取数据
        return data;
    }
}